package com.jnevision.user.controller;

import java.time.LocalDate;
import java.time.Year;
import java.time.YearMonth;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.api.ApiController;
import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.crtland.landoss.LandOss;
import com.crtland.landoss.Oss;
import com.crtland.landoss.OssInfo;
import com.crtland.landoss.OssType;
import com.crtland.landoss.PathEnum;
import com.crtland.landoss.Result;
import com.jnevision.common.CommonQuery;
import com.jnevision.config.ErrorCode;
import com.jnevision.dept.model.Dept;
import com.jnevision.dept.service.DeptServiceImpl;
import com.jnevision.dict.model.Dict;
import com.jnevision.dict.service.DictServiceImpl;
import com.jnevision.insurancerate.mapper.InsuranceRateMapper;
import com.jnevision.insurancerate.model.InsuranceRate;
import com.jnevision.salary.model.Salary;
import com.jnevision.salary.service.SalaryServiceImpl;
import com.jnevision.salaryrecord.model.SalaryRecord;
import com.jnevision.salaryrecord.service.SalaryRecordServiceImpl;
import com.jnevision.sysconfig.service.ConfigServiceImpl;
import com.jnevision.user.model.User;
import com.jnevision.user.model.UserStatistics;
import com.jnevision.user.model.UserVO;
import com.jnevision.user.service.UserServiceImpl;
import com.jnevision.userdept.model.UserDept;
import com.jnevision.userdept.service.UserDeptServiceImpl;
import com.jnevision.userrole.model.UserRole;
import com.jnevision.userrole.service.UserRoleServiceImpl;
import com.jnevision.util.Base64Util;
import com.jnevision.util.DateUtil;
import com.jnevision.util.JsonMapper;

/**
 * <p>
 * 用户 前端控制器
 * </p>
 *
 * @author gavin
 * @since 2019-07-13
 */

@RestController
@RequestMapping("/users")
public class UserController extends ApiController {
    private static final String INIT_PSWD = "12345678";
    @Autowired
    private UserServiceImpl userServiceImpl;
    @Autowired
    private SalaryServiceImpl salaryServiceImpl;
    @Autowired
    private UserDeptServiceImpl userDeptServiceImpl;
    @Autowired
    private UserRoleServiceImpl userRoleServiceImpl;
    @Autowired
    private OssInfo ossInfo;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private SalaryRecordServiceImpl salaryRecordServiceImpl;
    @Autowired
    private InsuranceRateMapper insuranceRateMapper;

    @Autowired
    private DeptServiceImpl deptServiceImpl;
    @Autowired
    private DictServiceImpl dictServiceImpl;
    @Autowired
    private ConfigServiceImpl configServiceImpl;

    @Transactional
    @PostMapping
    public R<Boolean> add(@RequestBody UserVO user) {

        user.setValid(true);
        user.setPassword(DigestUtils.md5DigestAsHex(INIT_PSWD.getBytes()));

        LandOss landOss = new LandOss(redisTemplate);
        Oss oss = landOss.getLandOss(OssType.ALI, ossInfo);

        if (StringUtils.isNotEmpty(user.getAvatar())) {

            try {
                Result result = oss.upload(PathEnum.MATERIAL, Base64Util.base64ToMultipart(user.getAvatar()));
                if (result.getStatus()) {
                    user.setAvatar(result.getFileUrl());
                } else {
                    return this.failed("banner图上传失败，请重试");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        int wy = Year.now().getValue() - LocalDate.parse(user.getEntryTime()).getYear();
        User u = new User();
        BeanUtils.copyProperties(user, u);
        u.setInsurance(user.isInsurance());
        u.setValid(true);
        u.setSigning(true);
        u.setWorksYear(wy);
        u.setAnnualSalary(user.isAnnualSalary());
        if (user.getRoleId() != 4) {
            u.setManager(true);
        } else {
            u.setManager(false);
        }

        this.userServiceImpl.save(u); // 保存用户

        UserDept ud = new UserDept();
        ud.setDeptId(user.getDeptId());
        ud.setUserId(u.getId());
        this.userDeptServiceImpl.save(ud); // 用户部门

        UserRole ur = new UserRole();
        ur.setRoleId(user.getRoleId());
        ur.setUserId(u.getId());
        this.userRoleServiceImpl.save(ur); // 用户角色
        InsuranceRate rate = this.insuranceRateMapper.selectList(null).get(0); // 保险费率有且仅有一条
        Salary salary = new Salary();
        salary.setGangwei(user.getGangwei());
        salary.setBaozhang(user.getBaozhang());
        salary.setWxjishu(user.getWxjishu());
        salary.setShiye(this.salaryServiceImpl.multiply(user.getWxjishu(), rate.getShiye()));
        salary.setYiliao(this.salaryServiceImpl.multiply(user.getWxjishu(), rate.getYiliao()));
        salary.setYanglao(this.salaryServiceImpl.multiply(user.getWxjishu(), rate.getYanglao()));
        salary.setUserId(u.getId());
        salary.setGongling(
            this.salaryServiceImpl.multiply(u.getWorksYear().toString(), this.configServiceImpl.getValue("gongling")));

        SalaryRecord salaryRecord = new SalaryRecord();
        salaryRecord.setUserId(u.getId());
        salaryRecord.setDate(YearMonth.now().toString());
        salaryRecord.setDeptId(user.getDeptId());
        salaryRecord.setGangwei(user.getGangwei());
        salaryRecord.setBaozhang(user.getBaozhang());
        salaryRecord.setWxjishu(user.getWxjishu());
        salaryRecord.setShiye(salary.getShiye());
        salaryRecord.setYiliao(salary.getYiliao());
        salaryRecord.setYanglao(salary.getYanglao());
        salaryRecord.setShengyu(rate.getShengyu());
        salaryRecord.setGongling(salary.getGongling());
        this.salaryRecordServiceImpl.save(salaryRecord);

        return this.success(this.salaryServiceImpl.save(salary)); // 保存用户薪资
    }

    @PutMapping
    @Transactional
    public R<Boolean> update(@RequestBody UserVO user) {
        LandOss landOss = new LandOss(redisTemplate);
        Oss oss = landOss.getLandOss(OssType.ALI, ossInfo);

        try {
            Result result = oss.upload(PathEnum.MATERIAL, Base64Util.base64ToMultipart(user.getAvatar()));
            if (result.getStatus()) {
                user.setAvatar(result.getFileUrl());
            } else {
                return this.failed("banner图上传失败，请重试");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        User tmpUser = this.userServiceImpl.getById(user.getId());
        user.setPassword(tmpUser.getPassword());
        User u = new User();
        BeanUtils.copyProperties(user, u);
        u.setAnnualSalary(user.isAnnualSalary());
        u.setSigning(user.isSigning());
        u.setInsurance(user.isInsurance());
        u.setValid(user.isValid());
        if (user.getRoleId() != 4) {
            u.setManager(true);
        } else {
            u.setManager(false);
        }

        this.userServiceImpl.updateById(u);

        InsuranceRate rate = this.insuranceRateMapper.selectList(null).get(0); // 保险费率有且仅有一条
        Salary salary = new Salary();
        salary.setGangwei(user.getGangwei());
        salary.setBaozhang(user.getBaozhang());
        salary.setWxjishu(user.getWxjishu());
        salary.setShiye(this.salaryServiceImpl.multiply(user.getWxjishu(), rate.getShiye()));
        salary.setYiliao(this.salaryServiceImpl.multiply(user.getWxjishu(), rate.getYiliao()));
        salary.setYanglao(this.salaryServiceImpl.multiply(user.getWxjishu(), rate.getYanglao()));
        salary.setUserId(u.getId());

        UserDept ud = new UserDept();
        ud.setDeptId(user.getDeptId());
        ud.setUserId(u.getId());
        this.userDeptServiceImpl.remove(new QueryWrapper<UserDept>().eq("user_id", user.getId()));
        this.userDeptServiceImpl.save(ud); // 用户部门

        UserRole ur = new UserRole();
        ur.setRoleId(user.getRoleId());
        ur.setUserId(u.getId());
        this.userRoleServiceImpl.remove(new QueryWrapper<UserRole>().eq("user_id", user.getId()));
        this.userRoleServiceImpl.save(ur); // 用户角色

        SalaryRecord salaryRecord = this.salaryRecordServiceImpl
            .getOne(new QueryWrapper<SalaryRecord>().eq("user_id", user.getId()).orderByDesc("date").last("limit 1"));

        salaryRecord.setUserId(u.getId());
        salaryRecord.setDate(YearMonth.now().toString());
        salaryRecord.setDeptId(user.getDeptId());
        salaryRecord.setGangwei(user.getGangwei());
        salaryRecord.setBaozhang(user.getBaozhang());
        salaryRecord.setWxjishu(user.getWxjishu());
        salaryRecord.setShiye(salary.getShiye());
        salaryRecord.setYiliao(salary.getYiliao());
        salaryRecord.setYanglao(salary.getYanglao());
        salaryRecord.setGongling(salary.getGongling());
        this.salaryRecordServiceImpl.updateById(salaryRecord);

        return this.success(
            this.salaryServiceImpl.update(salary, new UpdateWrapper<Salary>().eq("user_id", salary.getUserId())));
    }

    @GetMapping
    public R<UserVO> get(String id) {
        User user = this.userServiceImpl.getById(id);
        user.setPassword("");

        UserVO userVo = new UserVO();

        Salary salary = this.salaryServiceImpl.getOne(new QueryWrapper<Salary>().eq("user_id", id));
        UserRole ur = this.userRoleServiceImpl.getOne(new QueryWrapper<UserRole>().eq("user_id", id));
        UserDept one = this.userDeptServiceImpl.getOne(new QueryWrapper<UserDept>().eq("user_id", id));
        BeanUtils.copyProperties(user, userVo);
        userVo.setDeptId(one.getDeptId());
        userVo.setAnnualSalary(user.isAnnualSalary());
        userVo.setSigning(user.isSigning());
        userVo.setInsurance(user.isInsurance());
        userVo.setValid(user.isValid());
        Dict one2 = this.dictServiceImpl.getOne(new QueryWrapper<Dict>().eq("type", "job").eq("value", user.getJob()));
        if (null != one2) {

            userVo.setJob(one2.getLabel());
        }

        if (null != salary) {
            userVo.setGangwei(salary.getGangwei());
            userVo.setBaozhang(salary.getBaozhang());
            userVo.setGongling(salary.getGongling());
            userVo.setWxjishu(salary.getWxjishu());
            userVo.setYanglao(salary.getYanglao());
            userVo.setYiliao(salary.getYiliao());
            userVo.setShiye(salary.getShiye());
            userVo.setJiabanfei(salary.getJiabanfei());
        }
        InsuranceRate rate = this.insuranceRateMapper.selectList(null).get(0); // 保险费率有且仅有一条
        userVo.setGongshang(rate.getGongshang());
        userVo.setShengyu(rate.getShengyu());

        if (null != ur) {
            userVo.setRoleId(ur.getRoleId());
        }

        return this.success(userVo);
    }

    @DeleteMapping
    public R<Boolean> delete(String id) {
        User user = this.userServiceImpl.getById(id);
        user.setLeavedate(DateUtil.getNormalTime());
        user.setValid(false);

        //
        // this.userDeptServiceImpl.remove(new QueryWrapper<UserDept>().eq("user_id", id));
        //
        // this.salaryServiceImpl.remove(new QueryWrapper<Salary>().eq("user_id", id));
        //
        // this.salaryRecordServiceImpl.remove(new QueryWrapper<SalaryRecord>().eq("user_id", id));

        return this.success(this.userServiceImpl.updateById(user));
    }

    @DeleteMapping("/list/{ids}")
    public R<Boolean> delete(@PathVariable String[] ids) {

        Collection<User> user = this.userServiceImpl.listByIds(Arrays.asList(ids));

        user.forEach(u -> {
            u.setLeavedate(DateUtil.getNormalTime());
            u.setValid(false);
        });

        return this.success(this.userServiceImpl.updateBatchById(user));
    }

    /**
     * 所有的用户分页数据
     * 
     * @param page
     * @param user
     * @return
     */
    @GetMapping("/page")
    public R<IPage<User>> page(Page<User> page, User user) {
        return this.success(this.userServiceImpl.page(page,
            new QueryWrapper<User>().eq("is_insurance", user.isInsurance())
                .eq(null != user.getDeptId(), "dept_id", user.getDeptId())
                .like(StringUtils.isNotEmpty(user.getName()), "name", user.getName())
                .between(StringUtils.isNotEmpty(user.getStart()) && StringUtils.isNotEmpty(user.getEnd()), "entry_time",
                    user.getStart(), user.getEnd())));
    }

    /**
     * 所有的用户分页数据
     * 
     * @param page
     * @param user
     * @return
     */
    @GetMapping("/pages")
    public R<IPage<UserVO>> pages(Page<UserVO> page, User user) {

        return this.success(this.userServiceImpl.pages(page, user));
    }

    /**
     * 根据部门获取部门内的用户
     * 
     * @param page
     * @param user
     * @param deptId
     * @return
     */
    @GetMapping("/dept")
    public R<IPage<User>> page(Page<User> page, User user, int deptId, @RequestHeader("token") String token) {
        // this.deptServiceImpl.getById(deptId).getType();
        return this.success(this.userServiceImpl.getUser(page, deptId, user));
    }

    /**
     * 修改密码
     * 
     * @param userId
     * @param newPassword
     * @param oldPassword
     * @return
     */
    @GetMapping("/password")
    public R<Boolean> updatePswd(String userId, String newPassword) {
        User user = new User();
        user.setId(userId);
        user.setPassword(DigestUtils.md5DigestAsHex(newPassword.getBytes()));

        return this.success(this.userServiceImpl.updateById(user));
    }

    /**
     * 校验密码
     * 
     * @param userId
     * @param oldPswd
     * @return
     */
    @GetMapping("/sure/pswd")
    public R<Boolean> surePswd(String userId, String oldPswd) {
        return this.success(
            this.userServiceImpl.getById(userId).getPassword().equals(DigestUtils.md5DigestAsHex(oldPswd.getBytes())));
    }

    /**
     * app用户信息的修改
     * 
     * @param user
     * @return
     */
    @PutMapping("/app")
    public R<Boolean> update(@RequestBody User user, @RequestHeader("token") String token) {
        LandOss landOss = new LandOss(redisTemplate);
        Oss oss = landOss.getLandOss(OssType.ALI, ossInfo);

        try {
            Result result = oss.upload(PathEnum.MATERIAL, Base64Util.base64ToMultipart(user.getAvatar()));
            if (result.getStatus()) {
                user.setAvatar(result.getFileUrl());

                User redisUser = this.userServiceImpl.getLoginUser(token);
                redisUser.setAvatar(user.getAvatar());

                this.redisTemplate.opsForValue().set(token, JsonMapper.nonDefaultMapper().toJson(redisUser));
            } else {
                return this.failed("banner图上传失败，请重试");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return this.success(this.userServiceImpl.updateById(user));
    }

    /**
     * web用户信息的修改
     * 
     * @param user
     * @return
     */
    @PutMapping("/web")
    public R<Boolean> updateUser(@RequestBody User user) {

        return this.success(this.userServiceImpl.updateById(user));
    }

    /**
     * app 人脸采集
     * 
     * @param phone
     * @param faceCode
     * @return
     */
    @GetMapping("/app/face")
    public R<Boolean> updateFaceCode(String phone, String faceCode) {
        User user = new User();
        user.setPhone(phone);
        user.setFaceCode(faceCode);

        boolean flag = this.userServiceImpl.update(user, new UpdateWrapper<User>().eq("phone", phone));
        if (flag) {
            return this.success(flag);
        }
        return this.failed("没有此用户信息");
    }

    /**
     * 入职人员
     * 
     * @param start
     * @param end
     * @param deptId
     * @return
     */
    @GetMapping("/entry")
    public R<List<UserVO>> entryUser(String start, Integer deptId) {
        String end = DateUtil.getNextMonth(start);
        return this.success(this.userServiceImpl.entryUser(start + "-01", end + "-01", deptId));
    }

    /**
     * 离职人员
     * 
     * @param start
     * @param end
     * @param deptId
     * @return
     */
    @GetMapping("/out")
    public R<List<UserVO>> outUser(String start, Integer deptId) {
        String end = DateUtil.getNextMonth(start);
        return this.success(this.userServiceImpl.outUser(start + "-01", end + "-01", deptId));
    }

    @GetMapping("/gongling")
    public R<List<Map<String, String>>> getGongling() {
        return this.userServiceImpl.getGongling();
    }

    @GetMapping("/statistics")
    public List<UserStatistics> mobilityOfPersonnel(CommonQuery commonQuery) {

        return this.userServiceImpl.userStatistics(commonQuery);
    }

    @Transactional
    @PostMapping("/add")
    public R<Boolean> addUser(@RequestBody UserVO user) {

        user.setValid(true);
        if (StringUtils.isNotEmpty(user.getPassword())) {
            user.setPassword(DigestUtils.md5DigestAsHex(user.getPassword().getBytes()));
        } else {
            user.setPassword(DigestUtils.md5DigestAsHex(INIT_PSWD.getBytes()));
        }

        User u = new User();
        BeanUtils.copyProperties(user, u);
        u.setInsurance(user.isInsurance());
        u.setValid(user.isValid());
        this.userServiceImpl.save(u); // 保存用户

        UserDept ud = new UserDept();
        ud.setDeptId(user.getDeptId());
        ud.setUserId(u.getId());
        this.userDeptServiceImpl.save(ud); // 用户部门

        UserRole ur = new UserRole();
        ur.setRoleId(user.getRoleId());
        ur.setUserId(u.getId());
        return this.success(this.userRoleServiceImpl.save(ur)); // 用户角色

    }

    @PutMapping("/avatar")
    public R<Boolean> updateAvatar(@RequestBody User user) {
        LandOss landOss = new LandOss(redisTemplate);
        Oss oss = landOss.getLandOss(OssType.ALI, ossInfo);

        try {
            Result result = oss.upload(PathEnum.MATERIAL, Base64Util.base64ToMultipart(user.getAvatar()));
            if (result.getStatus()) {
                user.setAvatar(result.getFileUrl());
            } else {
                return this.failed("banner图上传失败，请重试");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return this.success(this.userServiceImpl.updateById(user));
    }

    @GetMapping("/token")
    public R<User> getByToken(@RequestHeader(value = "token") String token) {
        User tokenUser =
            JsonMapper.nonDefaultMapper().fromJson(this.redisTemplate.boundValueOps(token).get(), User.class);
        if (!Objects.isNull(tokenUser)) {
            User user = this.userServiceImpl.getById(tokenUser.getId());
            user.setPassword("");
            UserRole one = this.userRoleServiceImpl.getOne(new QueryWrapper<UserRole>().eq("user_id", user.getId()));
            if (null != one) {

                user.setRoleId(one.getRoleId());
            }
            UserDept one2 = this.userDeptServiceImpl.getOne(new QueryWrapper<UserDept>().eq("user_id", user.getId()));
            if (null != one2) {
                user.setDeptId(one2.getDeptId());
            }
            Dept byId = this.deptServiceImpl.getById(user.getDeptId());
            if (null != byId) {

                user.setDeptName(byId.getName());
            }

            return this.success(user);
        }

        return R.failed(ErrorCode.NO_LOGIN);
    }

    // @PostMapping("/uploadImg")
    // public void uploadTouxiang(@RequestParam("files") List<MultipartFile> files) {
    //
    // for (int i = 0; i < files.size(); i++) {
    // String str = files.get(i).getOriginalFilename();
    // String str2 = "";
    //
    // if (str != null && !"".equals(str)) {
    // for (int j = 0; j < str.length(); j++) {
    // if (str.charAt(j) >= 48 && str.charAt(j) <= 57) {
    // str2 += str.charAt(j);
    // }
    // }
    // }
    //
    // User user = this.userServiceImpl.getOne(new QueryWrapper<User>().eq("phone", str2));
    //
    // if (null != user) {
    //
    // byte[] bytes = (user.getName() + user.getPhone()).getBytes();
    //
    // String md5Digest = DigestUtils.md5DigestAsHex(bytes);
    //
    // user.setFaceCode(md5Digest);
    //
    // String add = FaceAdd.add(user.getAvatar(), user.getFaceCode(), "test_face_group");
    //
    // this.userServiceImpl.updateById(user);
    // }
    //
    // }
    //
    // }

}
